pacman::p_load(readxl, gifski, gapminder,
plotly, gganimate, tidyverse)Hands-on Ex 3b - Programming Animated Statistical Graphics with R
3.1 Overview
When telling a story, animated graphics capture attention and leave a strong impression. In this exercise, we’ll use gganimate and plotly to create animated visualizations, while also reshaping data with tidyr and transforming it with dplyr.
3.1.1 Basic concepts of animation
Animations are created by generating multiple static plots, each reflecting a subset of the data. When these plots are combined, they form frames that appear to move, similar to a flipbook or cartoon.

3.1.2 Terminology
Before creating an animated statistical graph, it’s helpful to understand some key concepts -
Frame: In an animated line graph, each frame represents a moment in time or a category. When the frame changes, the data points update to reflect new information.
Animation Attributes: These are settings that control how the animation plays such as frame duration, easing functions, and whether it starts at the current frame or from the beginning.
3.2 Getting Started
3.2.1 Loading the R packages
First, we write the code to check, install and load the following R packages:
- plotly, for plotting interactive statistical graphs.
- gganimate, an ggplot extension for creating animated statistical graphs.
- gifski converts video frames to GIF animations using pngquant’s fancy features for efficient cross-frame palettes and temporal dithering. It produces animated GIFs that use thousands of colors per frame.
- gapminder: An excerpt of the data available at Gapminder.org. We just want to use its country_colors scheme.
- tidyverse, to support data science, analysis and communication task including creating static statistical graphs.
3.2.2 Importing the data
In this exercise, we import the Data worksheet from the GlobalPopulation Excel workbook and use the appropriate package from tidyverse to load the worksheet.
col <- c("Country", "Continent")
globalPop <- read_xls("data/GlobalPopulation.xls",
sheet="Data") %>%
mutate_each_(funs(factor(.)), col) %>%
mutate(Year = as.integer(Year))read_xls()of readxl package is used to import the Excel worksheet.mutate_each_()of dplyr package is used to convert all character data type into factor.mutateof dplyr package is used to convert data values of Year field into integer.
mutate_each_() was deprecated in dplyr 0.7.0, and funs() was deprecated in dplyr 0.8.0. As a result, we’ll use mutate_at() instead.
col <- c("Country", "Continent")
globalPop <- read_xls("data/GlobalPopulation.xls",
sheet="Data") %>%
mutate_at(col, as.factor) %>%
mutate(Year = as.integer(Year))Even, across() can be used to derive the same outputs.
col <- c("Country", "Continent")
globalPop <- read_xls("data/GlobalPopulation.xls",
sheet="Data") %>%
mutate(across(col, as.factor)) %>%
mutate(Year = as.integer(Year))3.3 Animated Data Visualisation: gganimate methods
gganimate extends the grammar of graphics as implemented by ggplot2 by adding classes that define animations over time:
transition_*(): Spreads data over time and sets relationships.view_*(): Adjusts positional scales during animation.shadow_*(): Determines how past or future data is displayed.enter_*()/exit_*(): Manages how data appears or disappears.ease_aes(): Controls the easing of aesthetics during transitions.
3.3.1 Building a static population bubble plot
The basic ggplot2 functions are used to create a static bubble plot in the code chunk below.
ggplot(globalPop, aes(x = Old, y = Young,
size = Population,
colour = Country)) +
geom_point(alpha = 0.7,
show.legend = FALSE) +
scale_colour_manual(values = country_colors) +
scale_size(range = c(2, 12)) +
labs(title = 'Year: {frame_time}',
x = '% Aged',
y = '% Young') 
3.3.2 Building the animated bubble plot
In the code chunk below:
transition_time(): Creates transitions through distinct states in time (e.g., Year).ease_aes(): Controls how aesthetics transition. Default is linear, with other options like quadratic, cubic, sine, circular, elastic, and bounce.
ggplot(globalPop, aes(x = Old, y = Young,
size = Population,
colour = Country)) +
geom_point(alpha = 0.7,
show.legend = FALSE) +
scale_colour_manual(values = country_colors) +
scale_size(range = c(2, 12)) +
labs(title = 'Year: {frame_time}',
x = '% Aged',
y = '% Young') +
transition_time(Year) +
ease_aes('linear') The animated bubble chart -

3.4 Animated Data Visualisation: plotly
In Plotly’s R package, ggplotly() and plot_ly() support animations via the frame argument. They also offer an ids argument to ensure smooth transitions between objects sharing the same id, maintaining object constancy.
3.4.1 Building an animated bubble plot: ggplotly() method
In this sub-section, we create an animated bubble plot using ggplotly()
The animated bubble plot above includes a play/pause button and a slider component for controlling the animation.
gg <- ggplot(globalPop,
aes(x = Old,
y = Young,
size = Population,
colour = Country)) +
geom_point(aes(size = Population,
frame = Year),
alpha = 0.7,
show.legend = FALSE) +
scale_colour_manual(values = country_colors) +
scale_size(range = c(2, 12)) +
labs(x = '% Aged',
y = '% Young')
ggplotly(gg)- Appropriate ggplot2 functions are used to create a static bubble plot. The output is then saved as an R object called gg.
ggplotly()is then used to convert the R graphic object into an animated svg object.
Although show.legend = FALSE was used, the legend still appears. To fix this, use theme(legend.position='none'), as shown in the code below.
gg <- ggplot(globalPop,
aes(x = Old,
y = Young,
size = Population,
colour = Country)) +
geom_point(aes(size = Population,
frame = Year),
alpha = 0.7) +
scale_colour_manual(values = country_colors) +
scale_size(range = c(2, 12)) +
labs(x = '% Aged',
y = '% Young') +
theme(legend.position='none')
ggplotly(gg)3.4.2 Building an animated bubble plot: plot_ly() method
In this sub-section, we will create an animated bubble plot using plot_ly().
bp <- globalPop %>%
plot_ly(x = ~Old,
y = ~Young,
size = ~Population,
color = ~Continent,
sizes = c(2, 100),
frame = ~Year,
text = ~Country,
hoverinfo = "text",
type = 'scatter',
mode = 'markers'
) %>%
layout(showlegend = FALSE)
bp3.5 Reference
- Getting Started
- Visit this link for a very interesting implementation of gganimate by your senior.
- Building an animation step-by-step with gganimate.
- Creating a composite gif with multiple gganimate panels